home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / vbdatabs / part.cpp < prev    next >
C/C++ Source or Header  |  1999-03-17  |  9KB  |  323 lines

  1. // ------------------------------- //
  2. // -------- Start of File -------- //
  3. // ------------------------------- //
  4. // ----------------------------------------------------------- // 
  5. // C++ Source Code File Name: part.cpp 
  6. // Compiler Used: MSVC40, DJGPP 2.7.2.1, GCC 2.7.2.1, HP CPP 10.24
  7. // Produced By: Doug Gaer 
  8. // File Creation Date: 09/18/1997  
  9. // Date Last Modified: 03/17/1999
  10. // Copyright (c) 1997 Douglas M. Gaer
  11. // ----------------------------------------------------------- // 
  12. // ------------- Program Description and Details ------------- // 
  13. // ----------------------------------------------------------- // 
  14. /*
  15. This is a test program use to test the (P)ersistent base class.
  16.  
  17. The VBD C++ classes are copyright (c) 1997, by Douglas M. Gaer.
  18. All those who put this code or its derivatives in a commercial
  19. product MUST mention this copyright in their documentation for
  20. users of the products in which this code or its derivative
  21. classes are used. Otherwise, you have the freedom to redistribute
  22. verbatim copies of this source code, adapt it to your specific
  23. needs, or improve the code and release your improvements to the
  24. public provided that the modified files carry prominent notices
  25. stating that you changed the files and the date of any change.
  26.  
  27. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
  28. THE ENTIRE RISK OF THE QUALITY AND PERFORMANCE OF THIS SOFTWARE
  29. IS WITH YOU. SHOULD ANY ELEMENT OF THIS SOFTWARE PROVE DEFECTIVE,
  30. YOU WILL ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
  31. CORRECTION.
  32. */
  33. // ----------------------------------------------------------- // 
  34. #include "part.h"
  35.  
  36. __UWORD__ Part::ObjectLength()
  37. {
  38.   return sizeof(id) + sizeof(price) + StringFileLength(name);
  39. }
  40.  
  41. FAU Part::Write()
  42. {
  43.   ObjectHeader oh;
  44.   FAU addr = pod->OpenDatabase()->Alloc(ObjectLength() + sizeof(ObjectHeader));
  45.   if(!addr) return 0;
  46.   
  47.   oh.ClassID = GetClassID();
  48.   oh.ObjectID = addr;
  49.   WriteObjHeader(oh); 
  50.  
  51.   pod->OpenDatabase()->Write(&id, sizeof(id));
  52.   pod->OpenDatabase()->Write(&price, sizeof(price));
  53.   WriteString(name);
  54.   objectaddress = addr;  
  55.  
  56.   // Write a 32-bit CRC checksum for the object
  57.   pod->OpenDatabase()->WriteObjectChecksum(addr);
  58.                  
  59.   // Add the entry to the Index file
  60.   if (UsingIndex()) {
  61.     EntryKey key(name.c_str(), oh.ObjectID, oh.ClassID);
  62.     AddKey(key);
  63.   }
  64.   return addr;
  65. }
  66.  
  67. void Part::Read(FAU Address)
  68. {
  69.   ObjectHeader oh;
  70.  
  71.   // Optimize seeks during intervening reads
  72.   pod->OpenDatabase()->SeekTo(Address);
  73.  
  74.   ReadObjHeader(oh, Address);
  75.   if(oh.ClassID != GetClassID()) return; // Incorrect object type
  76.   pod->OpenDatabase()->Read(&id, sizeof(id));
  77.   pod->OpenDatabase()->Read(&price, sizeof(price));
  78.   ReadString(name);
  79.   objectaddress = Address;
  80.  
  81.   // Test the objects checksum
  82.   int rv = pod->OpenDatabase()->ReadObjectChecksum(Address);
  83.   if(!rv)
  84. #ifdef CPP_EXCEPTIONS
  85.     throw CChecksumError();
  86. #else
  87.   Error->SignalException(EHandler::ChecksumError, EHandler::DISPLAY);
  88. #endif
  89. }
  90.  
  91. FAU Part::Find()
  92. {
  93.   int rv; // Return value
  94.  
  95.   // Search the index file for this entry
  96.   if(UsingIndex()) {
  97.     EntryKey e(this->name.c_str());
  98.     rv = FindKey(e);
  99.     if(rv)  // Found the object in the index file
  100.       return e.object_address;
  101.   }
  102.  
  103.   // If not using index file or entry not found, search the data file
  104.   Part part;
  105.   FAU oa;          // Object Address
  106.   VBHeader vb;     // Variable Block Header
  107.   ObjectHeader oh; // Object Header
  108.   
  109.   FAU vbdfileEOF = pod->OpenDatabase()->GetEOF();
  110.   FAU addr = 0;
  111.   addr = pod->OpenDatabase()->FindFirstVB(addr); // Search the entire file
  112.  
  113.   if(addr == 0) return 0; // No variable blocks found in file
  114.  
  115.   part.id = this->id;
  116.   part.price = this->price;
  117.   part.name = this->name;
  118.  
  119.   while(1) { 
  120.     if(addr >= vbdfileEOF) break;
  121.     pod->OpenDatabase()->Read(&vb, sizeof(VBHeader), addr);
  122.     if(vb.CkWord == CheckWord) {
  123.       if((__SBYTE__)vb.Status == NormalVB) {
  124.     oa = addr + sizeof(VBHeader);
  125.     ReadObjHeader(oh, oa);
  126.     if(oh.ClassID == GetClassID()) { 
  127.       Read(oa);
  128.       if(name == part.name) {
  129.         objectaddress = oa;
  130.         return oa; // Found unique data member
  131.       }
  132.     }
  133.       }
  134.       addr = addr + vb.Length; // Goto the next variable block
  135.     }
  136.     else {
  137.       addr = pod->OpenDatabase()->VBSearch(addr); 
  138.       if(!addr) break;
  139.     }
  140.   }
  141.  
  142.   // Reset the objects data
  143.   this->id = part.id;
  144.   this->price = part.price;
  145.   this->name = part.name;
  146.   
  147.   return 0; // Could not find 
  148. }
  149.  
  150. FAU Part::Delete()
  151. {
  152.   if(UsingIndex()) {
  153.     EntryKey e(this->name.c_str());
  154.     int rv = FindKey(e);
  155.     if(rv) {  // Found the object in the index file
  156.       FAU addr = e.object_address;
  157.       DeleteObject(e.object_address); // Delete from the data file
  158.       RemoveKey(e);                   // Remove from the index file
  159.       return addr;
  160.     }
  161.     else
  162.       return 0; // Could not delete
  163.   }
  164.  
  165.   FAU addr = Find();
  166.   if(!addr) return 0; // Object does not exist
  167.   DeleteObject(addr);
  168.   return addr;
  169. }
  170.  
  171. FAU Part::Remove()
  172. {
  173.   if(UsingIndex()) {
  174.     EntryKey e(this->name.c_str());
  175.     int rv = FindKey(e);
  176.     if(rv) {  // Found the object in the index file
  177.       FAU addr = e.object_address;
  178.       RemoveObject(e.object_address); // Remove from the data file
  179.       RemoveKey(e);                   // Remove from the index file
  180.       return addr;
  181.     }
  182.     else
  183.       return 0; // Could not remove
  184.   }
  185.  
  186.   FAU addr = Find();
  187.   if(!addr) return 0; // Object does not exist
  188.   RemoveObject(addr);
  189.   return addr;
  190. }
  191.  
  192. int Part::CompareIndex()
  193. // Compares the data file to the index file.
  194. // Returns true if data and index file match.
  195. {
  196.   if(!UsingIndex()) return 0;
  197.  
  198.   // Ensure that the in memory buffers and the file data
  199.   // stay in sync during multiple file access.
  200.   pod->Index()->TestTree();
  201.  
  202.   Part part(pod);
  203.   EntryKey key;
  204.   
  205.   FAU oa;          // Object Address
  206.   VBHeader vb;     // Variable Block Header
  207.   ObjectHeader oh; // Object Header
  208.   
  209.   int objects = 0; // Keeps track of good variable blocks
  210.   int matches = 0; // Keep track of matches
  211.   
  212.   FAU vbdfileEOF = pod->OpenDatabase()->GetEOF();
  213.   FAU addr = 0;
  214.   addr = pod->OpenDatabase()->FindFirstVB(addr); // Search the entire file
  215.  
  216.   if(addr == 0) // No variable blocks found in file
  217. #ifdef CPP_EXCEPTIONS
  218.     throw CNoObjectsExist();
  219. #else
  220.     Error->SignalException(EHandler::NoObjectsExist);
  221. #endif
  222.  
  223.   while(1) { 
  224.     if(addr >= vbdfileEOF) break;
  225.     pod->OpenDatabase()->Read(&vb, sizeof(VBHeader), addr);
  226.     if(vb.CkWord == CheckWord) {
  227.       if((__SBYTE__)vb.Status == NormalVB) {
  228.     oa = addr + sizeof(VBHeader);
  229.     ReadObjHeader(oh);
  230.     if(oh.ClassID == GetClassID()) { 
  231.       objects++; // Increment the object count
  232.       part.Read(oa);
  233.       key.SetStrKey(part.GetName());
  234.       key.SetOA(oa);
  235.       key.SetCID(oh.ClassID);
  236.       int rv = FindKey(key, 1);
  237.       if(rv) matches++; // Index and data file match
  238.     }
  239.       }
  240.       addr = addr + vb.Length; // Goto the next variable block
  241.     }
  242.     else {
  243.       addr = pod->OpenDatabase()->VBSearch(addr); 
  244.       if(!addr) break;
  245.     }
  246.   }
  247.  
  248.   return objects == matches;
  249. }
  250.  
  251. int Part::RebuildIndexFile(const char *fname)
  252. {
  253.   if(!UsingIndex()) return 0;
  254.  
  255.   int rv; // (R)eturn (V)alue
  256.   int CacheSize = 15;
  257.  
  258.   VBDFilePtr f(new VBDFile);
  259.   Btree btx(CacheSize);
  260.   f->Create(fname, sizeof(BtreeHeader));
  261.   btx.Connect(f, 1);
  262.   
  263.   Part part(pod);
  264.   EntryKey key;
  265.   
  266.   FAU oa;          // Object Address
  267.   VBHeader vb;     // Variable Block Header
  268.   ObjectHeader oh; // Object Header
  269.   
  270.   int objects = 0; // Keeps track of good variable blocks
  271.   int inserts = 0; // Keep track of inserts
  272.   
  273.   FAU vbdfileEOF = pod->OpenDatabase()->GetEOF();
  274.   FAU addr = 0;
  275.   addr = pod->OpenDatabase()->FindFirstVB(addr); // Search the entire file
  276.  
  277.   if(addr == 0) // No variable blocks found in file
  278. #ifdef CPP_EXCEPTIONS
  279.     throw CNoObjectsExist();
  280. #else
  281.     Error->SignalException(EHandler::NoObjectsExist);
  282. #endif
  283.  
  284.   while(1) { 
  285.     if(addr >= vbdfileEOF) break;
  286.     pod->OpenDatabase()->Read(&vb, sizeof(VBHeader),